import uvicorn
from litestar import Litestar, Router
from litestar.contrib.sqlalchemy.plugins import (
    SQLAlchemyInitPlugin,
    SQLAlchemySerializationPlugin,
)
from litestar.openapi import OpenAPIConfig
from litestar.plugins.structlog import StructlogPlugin
from litestar.static_files import create_static_files_router

from config import setting
from controller.todo_item import TodoItemController
from controller.user import UserController
from core.dependency import provide_limit_offset_pagination
from core.log import structlog_config
from core.plugin import (
    rapid_doc_render_plugin,
    redoc_render_plugin,
    stop_light_render_plugin,
    swagger_render_plugin,
)
from db.connect import provide_transaction, sqlalchemy_config


def create_app() -> Litestar:
    # 加载静态文件
    static_file_router = create_static_files_router(
        path=setting.STATIC_URL,
        directories=[setting.STATIC_ROOT],
    )

    # 自定义 OpenAPI，使用本地 CDN，解决静态文件无法访问的问题
    openapi_config = OpenAPIConfig(
        title="ZIC API",
        version="1.0.0",
        render_plugins=[
            stop_light_render_plugin,
            rapid_doc_render_plugin,
            redoc_render_plugin,
            swagger_render_plugin,
        ],
    )

    # 定义 API 路由
    api_router = Router(
        path="/api",
        route_handlers=[TodoItemController, UserController],
    )

    # 初始化 Litestar app
    app = Litestar(
        route_handlers=[static_file_router, api_router],
        # after_exception=[after_exception_handler],
        openapi_config=openapi_config,
        dependencies={
            "transaction": provide_transaction,
            "limit_offset": provide_limit_offset_pagination,
        },
        # lifespan=[db_connection],
        plugins=[
            SQLAlchemySerializationPlugin(),
            SQLAlchemyInitPlugin(sqlalchemy_config),
            StructlogPlugin(structlog_config),
        ],
    )

    return app


app = create_app()

if __name__ == "__main__":
    # 获取服务器配置
    server_config = setting.CONFIG["server"]
    # 以 uvicorn 启动 litestar 服务
    uvicorn.run(
        app="app:app",
        host=server_config["host"],
        port=server_config["port"],
        reload=server_config["reload"],
        workers=server_config["workers"],
    )
